package leeon.bbsbrower.util;

import ipworks.IPWorksException;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import leeon.bbsbrower.BBSBrowerPlugin;
import leeon.bbsbrower.actions.Config;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ProgressIndicator;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.PlatformUI;

public class ImageDownloadManager implements Runnable {
	
	private static ImageDownloadManager manager;
	
	public synchronized static ImageDownloadManager newInstance() {
		if (manager == null) {
			manager = new ImageDownloadManager(5);
			Thread t = new Thread(manager);
			t.start();
		}
		return manager;
	}
	
	List<String> waiting = new ArrayList<String>();
	
	ProgressMonitor[] monitors = null;
	HTTPBean[] https = null;
	
	Label listLabel = null;
	
	private ImageDownloadManager(int max) {
		
		monitors = new ProgressMonitor[max];
		https = new HTTPBean[max];
		
	}
	
	public synchronized void setUI(int index, ProgressIndicator progressIndicator, Label messageLabel) {
		monitors[index].setUI(progressIndicator, messageLabel);
	}
	
	public synchronized void setLabel(Label listLabel) {
		this.listLabel = listLabel;
		updateListLabel();
	}
	
	public synchronized void removeLabel() {
		this.listLabel = null;
	}
	
	public synchronized int needUI() {
		for (int i = 0; i < monitors.length; i ++) {
			if (!monitors[i].haveUI()) return i;
		}
		return -1;
	}
	
	private void updateListLabel() {
		if (this.listLabel != null && !this.listLabel.isDisposed()) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < waiting.size(); i ++) {
				sb.append(waiting.get(i)).append("\n");
			}
			listLabel.setText(sb.toString());
			listLabel.update();
		}
		
	}
	
	public synchronized void removeAllUI() {
		for (int i = 0; i < monitors.length; i ++)
			monitors[i].removeUI();
	}
	
		
	public void run() {
		
		synchronized(this) {
			for (int i = 0; i < https.length; i ++) {
				monitors[i] = new ProgressMonitor();
				try {
					https[i] = HTTPBean.newAnotherInstance(Config.PROXY_SERVER, Config.PROXY_PORT, Config.PROXY_USER, Config.PROXY_PASSWORD);
				} catch (IPWorksException e) {
					e.printStackTrace();
				}
				https[i].setMonitor(monitors[i]);
			}
		}
		
		while (true) {
			
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			if (waiting.size() == 0) continue;
			
			//获取可用的monitor
			for (int i = 0; i < monitors.length; i ++) {
				if (monitors[i].isDone()) {
					final HTTPBean http = https[i];
					final ProgressMonitor monitor = monitors[i];
					final String url = waiting.remove(0);
					PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
						public void run() {
							updateListLabel();
						}
					});
					
					
					
					Thread t = new Thread(new Runnable() {
						public void run() {
							//准备下载
							String name = BrowerImages.dealImageName(url);
							
							try {
								ByteArrayOutputStream b = http.getAsStream(url);
								
								//保存
								File dir = BBSBrowerPlugin.getRealFile(BrowerImages.PIC_PATH);
								FileOutputStream fos = new FileOutputStream(new File(dir.getAbsolutePath() + "/" +name));
								fos.write(b.toByteArray());
								fos.close();
								BrowerImages.addStandbyImage(name);
								
								//关闭
								b.close();
								
							} catch (Exception e) {
								e.printStackTrace();
								BrowerImages.addBadImage(name);
								PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
									public void run() {
										monitor.done();
									}
								});
								
							}	
						}
					});
					t.start();
					
					if (waiting.size() == 0) break;
				}
			}
		}
	}
	
	public synchronized void addImageUrl(String url) {
		String name = BrowerImages.dealImageName(url);
		BrowerImages.addDownloadingImage(name);
		waiting.add(url);
	}

}



class ProgressMonitor implements IProgressMonitor {
	
	private ProgressIndicator progressIndicator;
	private Label messageLabel;
	private boolean done = true;
	private String name = "OK";
	private int totalWork;
	private double work;
	
	public synchronized void beginTask(String name, int totalWork) {
		this.name = name;
		this.totalWork = totalWork;
		this.work = 0;
		this.done = false;
				
		if (this.messageLabel != null && !this.messageLabel.isDisposed()) {
			this.messageLabel.setText(this.name);
			this.messageLabel.update();
		}
		
		if (this.progressIndicator != null && !this.progressIndicator.isDisposed()) {
			this.progressIndicator.done();
			if (totalWork == UNKNOWN) {
				this.progressIndicator.beginAnimatedTask();
	        } else {
	        	this.progressIndicator.beginTask(this.totalWork);
	        }
		}
		
	}

	public synchronized void done() {
		this.done = true;
		this.name = "OK";
		this.totalWork = 0;
		this.work = 0;
		
		if (this.messageLabel != null && !this.messageLabel.isDisposed()) {
			this.messageLabel.setText(this.name);
			this.messageLabel.update();
		}
		
		if (progressIndicator != null && !progressIndicator.isDisposed()) {
            progressIndicator.sendRemainingWork();
            progressIndicator.done();
        }
		
	}

	public synchronized void internalWorked(double work) {
		double i = work - this.work; 
		this.work = work;
		if (progressIndicator != null && !progressIndicator.isDisposed()) {			
			progressIndicator.worked(i);
		}
	}
	
	public synchronized void worked(int work) {
		internalWorked(work);
	}
	
	public synchronized void setUI(ProgressIndicator progressIndicator, Label messageLabel) {
		this.progressIndicator = progressIndicator;
		this.messageLabel = messageLabel;
		this.progressIndicator.sendRemainingWork();
		this.progressIndicator.done();
		
		if (this.totalWork == UNKNOWN) {
			this.progressIndicator.beginAnimatedTask();
			this.progressIndicator.worked(this.work);
        } else if (this.totalWork != 0) {
        	this.progressIndicator.beginTask(this.totalWork);
        	this.progressIndicator.worked(this.work);
        }
		
		this.messageLabel.setText(this.name);
		this.messageLabel.update();
	}
	
	public synchronized void removeUI() {
		this.progressIndicator = null;
		this.messageLabel = null;
	}
	
	public synchronized boolean haveUI() {
		return (this.progressIndicator != null && this.messageLabel != null);
	}
	
	public synchronized boolean isDone() {
		return this.done;
	}
		
	public boolean isCanceled() {return false;}
	public void setCanceled(boolean value) {}
	public void setTaskName(String name) {}
	public void subTask(String name) {}	
}